package com.luo.d3s.light.jpa.ec.domain.goods;

import com.luo.d3s.core.application.dto.PageResponse;
import com.luo.d3s.core.infrastructure.convertor.JpaPageConvertor;
import com.luo.d3s.light.jpa.ec.application.dto.query.GoodsPageQuery;
import com.luo.d3s.light.jpa.ec.application.dto.vo.GoodsTagVo;
import com.luo.d3s.light.jpa.ec.application.dto.vo.GoodsVo;
import com.luo.d3s.light.jpa.ec.domain.base.BaseRepository;
import com.luo.d3s.light.jpa.ec.domain.base.BizId;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;

/**
 * Goods repository
 *
 * @author luohq
 * @date 2022-11-27 18:35
 */
public interface GoodsRepository extends BaseRepository<Goods, BizId> {

    /**
     * 查询指定商品ID集合对应的商品数量
     *
     * @param ids 商品ID集合
     * @return 存在的商品数量
     */
    Integer countByIdIn(Collection<BizId> ids);

    /**
     * 分类下是否存在商品
     *
     * @param categoryIds 分类ID列表
     * @return 是否存在
     */
    Boolean existsByCategoryIdIn(Collection<BizId> categoryIds);

    /**
     * 是否存在指定状态（上架、下架）的商品
     *
     * @param goodsIds    商品ID列表
     * @param goodsStatus 商品状态
     * @return 是否存在
     */
    Boolean existsByIdInAndGoodsStatus(Collection<BizId> goodsIds, GoodsStatus goodsStatus);

    /**
     * 是否存在已上架的商品
     *
     * @param goodsIds    商品ID列表
     * @return 是否存在
     */
    @Query
    Boolean existsShelvedGoodsByIdIn(Collection<BizId> goodsIds);

    /**
     * 批量更新商品状态
     *
     * @param goodsIds    商品ID列表
     * @param goodsStatus 商品状态
     */
    @Modifying
    @Query
    void batchModifyGoodsStatus(@Param("goodsIds") Collection<BizId> goodsIds, @Param("goodsStatus") GoodsStatus goodsStatus);

    /**
     * 根据ID查询商品详情
     *
     * @param id 商品ID
     * @return 商品详情
     */
    @Query(nativeQuery = true)
    GoodsVo findGoodsWithCNameById(@Param("id") Long id);

    /**
     * 查询商品关联的标签信息集合
     *
     * @param goodsId 商品ID
     * @return 标签信息集合
     */
    @Query(nativeQuery = true)
    List<GoodsTagVo> findGoodsTags(@Param("goodsId") Long goodsId);

    /**
     * 标签下是否存在商品
     *
     * @param tagIds 标签ID列表
     * @return 是否存在
     */
    @Query(nativeQuery = true)
    Boolean existsByTagIds(@Param("tagIds") Collection<Long> tagIds);

    /**
     * 查询商品分页列表
     *
     * @param goodsPageQuery 具体查询参数
     * @return 分页查询结果
     */
    default PageResponse<GoodsVo> findGoodsWithCNamePage(GoodsPageQuery goodsPageQuery) {
        Page<GoodsVo> goodsWithCNamePage = this.findGoodsWithCNamePageJpa(
                goodsPageQuery.getGoodsName(),
                goodsPageQuery.getCategoryId(),
                goodsPageQuery.getStartGoodsPrice(),
                goodsPageQuery.getEndGoodsPrice(),
                goodsPageQuery.getGoodsStatus(),
                goodsPageQuery.getBeforeExpirationDate(),
                goodsPageQuery.getCreateTimeStart(),
                goodsPageQuery.getCreateTimeEnd(),
                JpaPageConvertor.toPage(goodsPageQuery));
        return JpaPageConvertor.toPageResponse(goodsWithCNamePage);
    }

    /**
     * 查询商品分页列表<br/>
     * 注：此处Pageable参数中的Sort排序不生效
     *
     * @param goodsName
     * @param categoryId
     * @param startGoodsPrice
     * @param endGoodsPrice
     * @param goodsStatus
     * @param beforeExpirationDate
     * @param createTimeStart
     * @param createTimeEnd
     * @param pageable
     * @return
     */
    @Query(nativeQuery = true)
    Page<GoodsVo> findGoodsWithCNamePageJpa(@Param("goodsName") String goodsName,
                                            @Param("categoryId") Long categoryId,
                                            @Param("startGoodsPrice") BigDecimal startGoodsPrice,
                                            @Param("endGoodsPrice") BigDecimal endGoodsPrice,
                                            @Param("goodsStatus") Integer goodsStatus,
                                            @Param("beforeExpirationDate") LocalDate beforeExpirationDate,
                                            @Param("createTimeStart") LocalDateTime createTimeStart,
                                            @Param("createTimeEnd") LocalDateTime createTimeEnd,
                                            Pageable pageable);
}
